const hre = require('hardhat');
/**
 * 卖出指定 launchId 的部分代币 (先 approve 再 sellTokens)
 * 环境变量:
 *  LAUNCHPAD_ADDRESS  LaunchPad 合约地址 (必填)
 *  LAUNCH_ID          发射 ID (默认 1)
 *  TOKEN_AMOUNT       卖出的代币数量(人类可读, 如 100.5) 与 PERCENT 互斥
 *  PERCENT            卖出当前余额百分比 (整数/小数, 如 5 或 12.5) 默认 10
 *  SKIP_APPROVE=1     如果已经授权过且 allowance 足够可跳过 approve
 *
 * 示例:
 *  LAUNCHPAD_ADDRESS=0xd9B7BDD6DbC80DaEc00fB0a6c920eA50C1eDF017 LAUNCH_ID=1 PERCENT=5 \
 *  npx hardhat run scripts/sell-tokens.js --network xlayerTerigon
 */
async function main(){
  const p = process.env;
  const launchPadAddr = p.LAUNCHPAD_ADDRESS;
  if(!launchPadAddr) throw new Error('请设置 LAUNCHPAD_ADDRESS 环境变量。示例: LAUNCHPAD_ADDRESS=0xd9B7BDD6DbC80DaEc00fB0a6c920eA50C1eDF017');
  const launchId = p.LAUNCH_ID ? parseInt(p.LAUNCH_ID) : 1;
  const percentStr = p.PERCENT || '10';
  const tokenAmountStr = p.TOKEN_AMOUNT; // 人类可读数量
  const skipApprove = p.SKIP_APPROVE === '1';

  if(tokenAmountStr && p.PERCENT){
    throw new Error('TOKEN_AMOUNT 与 PERCENT 不能同时设置');
  }

  console.log('=== Sell Tokens ===');
  console.log('Network:', hre.network.name);
  console.log('LaunchPad:', launchPadAddr, 'Launch ID:', launchId);

  const [signer] = await hre.ethers.getSigners();
  const user = await signer.getAddress();
  console.log('Seller:', user);

  const launchPad = await hre.ethers.getContractAt('XLayerLaunchPad', launchPadAddr, signer);
  const info = await launchPad.getLaunchInfo(launchId);
  const tokenAddress = info[0];
  if(tokenAddress === hre.ethers.ZeroAddress) throw new Error('Launch 不存在或 tokenAddress=0');
  console.log('Token Address:', tokenAddress);

  const erc20 = await hre.ethers.getContractAt([
    'function balanceOf(address) view returns (uint256)',
    'function decimals() view returns (uint8)',
    'function symbol() view returns (string)',
    'function allowance(address,address) view returns (uint256)',
    'function approve(address,uint256) returns (bool)'
  ], tokenAddress, signer);

  const [decimals, symbol] = await Promise.all([erc20.decimals(), erc20.symbol()]);
  const balance = await erc20.balanceOf(user);
  console.log('Current Token Balance:', balance.toString(), symbol);
  if(balance === 0n) throw new Error('余额为0，无法出售');

  let amountToSell;
  if(tokenAmountStr){
    const human = tokenAmountStr.trim();
    if(isNaN(Number(human)) || Number(human) <= 0) throw new Error('TOKEN_AMOUNT 非法');
    amountToSell = hre.ethers.parseUnits(human, decimals);
  } else {
    const pct = Number(percentStr);
    if(isNaN(pct) || pct <= 0 || pct > 100) throw new Error('PERCENT 需在 (0,100]');
    amountToSell = (balance * BigInt(Math.floor(pct * 10000))) / (10000n * 100n); // 支持小数百分比到 0.01 精度
  }
  if(amountToSell === 0n) throw new Error('计算后卖出数量为0');
  if(amountToSell > balance) amountToSell = balance; // 防溢出
  console.log('Amount To Sell (raw):', amountToSell.toString());

  // 显示当前价格与已售数量
  const priceBefore = info[10];
  const soldBefore = info[11];
  console.log('Price Before (ETH):', hre.ethers.formatEther(priceBefore));
  console.log('Tokens Sold (Before):', soldBefore.toString());

  // 余额前
  const ethBefore = await signer.provider.getBalance(user);

  // 授权
  if(!skipApprove){
    const allowance = await erc20.allowance(user, launchPadAddr);
    if(allowance < amountToSell){
      console.log('Approving amount ...');
      const approveTx = await erc20.approve(launchPadAddr, amountToSell);
      console.log('Approve tx:', approveTx.hash);
      await approveTx.wait();
    } else {
      console.log('已存在足够 allowance, 跳过 approve');
    }
  } else {
    console.log('跳过 approve (SKIP_APPROVE=1)');
  }

  console.log('Calling sellTokens ...');
  const sellTx = await launchPad.sellTokens(launchId, amountToSell);
  console.log('Sell tx:', sellTx.hash);
  const sellReceipt = await sellTx.wait();
  console.log('Mined block:', sellReceipt.blockNumber);

  // 读取 after 信息
  const infoAfter = await launchPad.getLaunchInfo(launchId);
  const priceAfter = infoAfter[10];
  const soldAfter = infoAfter[11];
  const balanceAfter = await erc20.balanceOf(user);
  const ethAfter = await signer.provider.getBalance(user);

  console.log('\n=== After Sell ===');
  console.log('Price After (ETH):', hre.ethers.formatEther(priceAfter));
  console.log('Tokens Sold (After):', soldAfter.toString());
  console.log('Token Balance After:', balanceAfter.toString(), symbol);
  const ethDelta = ethAfter - ethBefore; // 包含 gas，可能略低于预期
  console.log('ETH Delta (含 gas):', hre.ethers.formatEther(ethDelta));
  console.log('ETH Balance After:', hre.ethers.formatEther(ethAfter));
  console.log('\n完成: 卖出执行成功。');
}

main().catch(e=>{console.error(e);process.exit(1);});
